home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
ULARN.ARJ
/
ULARN.TAR
/
ularn
/
monster.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-10-25
|
47KB
|
2,117 lines
/*
* monster.c
*
* This file contains the following functions:
* ------------------------------------------------------------------------
*
* createmonster(monstno) Function to create a monster next to the player
* int monstno;
*
* int cgood(x,y,itm,monst) Function to check location for emptiness
* int x,y,itm,monst;
*
* createitem(it,arg) Routine to place an item next to the player
* int it,arg;
*
* cast() Subroutine called by parse to cast a spell for the user
*
* speldamage(x) Function to perform spell functions cast by the player
* int x;
*
* loseint() Routine to decrement your int (intelligence) if > 3
*
* isconfuse() Routine to check to see if player is confused
*
* nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster
* int x,monst;
*
* fullhit(xx) Function to return full damage against a monst (aka web)
* int xx;
*
* Routine to direct spell damage 1 square in 1 dir
* direct(spnum,dam,str,arg)
* int spnum,dam,arg;
* char *str;
*
* Function to perform missile attacks
* godirect(spnum,dam,str,delay,cshow)
* int spnum,dam,delay;
* char *str,cshow;
*
* Routine to put "monster" or the monster name into lastmosnt
* ifblind(x,y)
* int x,y;
*
* tdirect(spnum) Routine to teleport away a monster
* int spnum;
*
* Routine to damage all monsters 1 square from player
* omnidirect(sp,dam,str)
* int sp,dam;
* char *str;
*
* dirsub(x,y) Routine to ask for direction, then modify x,y for it
* int *x,*y;
*
* vxy(x,y) Routine to verify/fix (*x,*y) for being within bounds
* int *x,*y;
*
* dirpoly(spnum) Routine to ask for a direction and polymorph a monst
* int spnum;
*
* hitmonster(x,y) Function to hit a monster at the designated coordinates
* int x,y;
*
* hitm(x,y,amt) Function to just hit a monster at a given coordinates
* int x,y,amt;
*
* hitplayer(x,y) Function for the monster to hit the player from (x,y)
* int x,y;
*
* dropsomething(monst) Function to create an object when a monster dies
* int monst;
*
* dropgold(amount) Function to drop some gold around player
* int amount;
*
* something(level) Function to create a random item around player
* int level;
*
* newobject(lev,i) Routine to return a randomly selected new object
* int lev,*i;
*
* spattack(atckno,xx,yy) Function to process special attacks from monsters
* int atckno,xx,yy;
*
* Routine to subtract hp from user and flag bottomline display
* checkloss(x)
* int x;
*
* Routine to annihilate monsters around player, playerx,playery
* annihilate()
*
* Function to create a new sphere of annihilation
* newsphere(x,y,dir,lifetime)
* int x,y,dir,lifetime;
*
* rmsphere(x,y) Function to delete a sphere of annihilation from list
* int x,y;
*
* sphboom(x,y) Function to perform the effects of a sphere detonation
* int x,y;
*
* genmonst() Function to ask for monster and genocide from game
*
*/
#include "header.h"
struct isave /* used for altar reality */
{
char type; /* 0=item, 1=monster */
char id; /* item number or monster number */
short arg; /* the type of item or hitpoints of monster */
};
/*
* Function to create a monster next to the player
* createmonster(monstno)
* int monstno;
*
* Enter with the monster number (1 to MAXMONST+8)
* Returns no value.
*/
createmonster(mon)
int mon;
{
register int x,y,k,i;
if (mon<1 || mon>MAXMONST+8) {
beep();
lprintf("\ncan't createmonst(%d)\n",(long)mon);
nap(3000);
return;
}
while (monster[mon].genocided && mon<MAXMONST)
mon++; /* genocided? */
for (k=rnd(8), i= -8; i<0; i++,k++)/* choose direction, then try all */
{
if (k>8) k=1; /* wraparound the diroff arrays */
x = playerx + diroffx[k];
y = playery + diroffy[k];
if (cgood(x,y,0,1)) /* if we can create here */
{
mitem[x][y] = mon;
hitp[x][y] = monster[mon].hitpoints;
stealth[x][y]=know[x][y]=0;
switch(mon) {
case ROTHE:
case POLTERGEIST:
case VAMPIRE:
stealth[x][y]=1;
};
return;
}
}
}
/*
* int cgood(x,y,itm,monst) Function to check location for emptiness
* int x,y,itm,monst;
*
* Routine to return TRUE if a location does not have itm or monst there
* returns FALSE (0) otherwise
* Enter with itm or monst TRUE or FALSE if checking it
* Example: if itm==TRUE check for no item at this location
* if monst==TRUE check for no monster at this location
* This routine will return FALSE if at a wall or the dungeon exit on level 1
*/
cgood(x,y,itm,monst)
register int x,y;
int itm,monst;
{
if ((y>=0) && (y<=MAXY-1)
&& (x>=0) && (x<=MAXX-1)) /* within bounds? */
if (item[x][y]!=OWALL) /* can't make on walls */
if (itm==0 || (item[x][y]==0)) /* is it free of items? */
if (monst==0 || (mitem[x][y]==0)) /*is it free of monsters? */
if ((level!=1) || (x!=33) || (y!=MAXY-1))
/* not exit to level 1 */
return(1);
return(0);
}
/*
* createitem(it,arg) Routine to place an item next to the player
* int it,arg;
*
* Enter with the item number and its argument (iven[], ivenarg[])
* Returns no value, thus we don't know about createitem() failures.
*/
createitem(it,arg)
int it;
long arg;
{
register int x,y,k,i;
if (it >= MAXOBJ)
return; /* no such object */
for (k=rnd(8), i= -8; i<0; i++,k++) { /* choose direction, try all */
if (k>8) k=1; /* wraparound the diroff arrays */
x = playerx + diroffx[k];
y = playery + diroffy[k];
if ( (it != OMAXGOLD && it != OGOLDPILE) ) {
if (cgood(x,y,1,0)) { /* if we can create here */
item[x][y] = it;
know[x][y]=0;
iarg[x][y]=arg;
return;
}
}
else {
int i;
switch (item[x][y]) {
case OGOLDPILE :
if ( (iarg[x][y] + arg) < 32767) {
iarg[x][y] += arg;
return;
}
case ODGOLD :
if ( (10 * iarg[x][y] + arg) < 327670L) {
i = iarg[x][y] ;
iarg[x][y] = (10 * i + arg) / 10;
item[x][y] = ODGOLD;
return;
}
case OMAXGOLD :
if ( (100 * iarg[x][y] + arg) < 3276700L) {
i = (100 * iarg[x][y]) + arg;
iarg[x][y] = i / 100;
item[x][y] = OMAXGOLD;
return;
}
case OKGOLD :
if ( (1000 * iarg[x][y] + arg) < 32767000L) {
i = iarg[x][y];
iarg[x][y] = (1000 * i + arg) / 1000;
item[x][y] = OKGOLD;
return;
}
else iarg[x][y] = 32767000L;
return;
default :
if (cgood(x,y,1,0)) {
item[x][y] = it;
know[x][y]=0;
if (it == OMAXGOLD)
iarg[x][y]= arg / 100;
else iarg[x][y]=arg;
return;
}
} /* end switch */
} /* end else */
} /* end for */
}
/*
* cast() Subroutine called by parse to cast a spell for the user
*
* No arguments and no return value.
*/
static char eys[] = "\nEnter your spell: ";
cast()
{
register int i,j,a,b,d;
cursors();
if (c[SPELLS]<=0) {
lprcat("\nYou don't have any spells!");
return;
}
lprcat(eys);
--c[SPELLS];
while ((a=getcharacter())=='D') {
seemagic(-1);
cursors();
lprcat(eys);
}
if (a=='\33') goto over; /* to escape casting a spell */
if ((b=getcharacter())=='\33') goto over; /*to escape casting a spell */
if ((d=getcharacter())=='\33') {
over:
lprcat(aborted);
c[SPELLS]++;
return;
} /* to escape casting a spell */
/*seq search for his spell, hash?*/
for (lprc('\n'),j= -1,i=0; i<SPNUM+1; i++)
if ((spelcode[i][0]==a) && (spelcode[i][1]==b) && (spelcode[i][2]==d))
if (spelknow[i]) {
speldamage(i);
j = 1;
i=SPNUM+1;
}
if (j == -1) lprcat(" Nothing Happened ");
bottomline();
}
/*
* speldamage(x) Function to perform spell functions cast by the player
* int x;
*
* Enter with the spell number, returns no value.
* Please insure that there are 2 spaces before all messages here
*/
speldamage(x)
int x;
{
register int i,j,clev;
int xl,xh,yl,yh;
register char *p,*kn,*pm;
if (x>=SPNUM+1) return; /* no such spell */
if (c[TIMESTOP]) {
lprcat(" It didn't seem to work");
return;
} /* not if time stopped */
if ((rnd(23)==7) || (rnd(18) > c[INTELLIGENCE]))
{
lprcat(" It didn't work!");
return;
}
clev = c[LEVEL];
if (clev*3+2 < x)
{
lprcat(" Nothing happens. You seem inexperienced at this");
return;
}
switch(x)
{
/* ----- LEVEL 1 SPELLS ----- */
case 0:
if (c[PROTECTIONTIME]==0)
c[MOREDEFENSES]+=2; /* protection field +2 */
c[PROTECTIONTIME] += 250;
return;
case 1:
i = rnd(((clev+1)<<1)) + clev + 3;
godirect(x,i,(clev>=2)?" Your missiles hit the %s":" Your missile hit the %s",100,'+'); /* magic missile */
return;
case 2:
if (c[DEXCOUNT]==0)
c[DEXTERITY]+=3; /* dexterity */
c[DEXCOUNT] += 400;
return;
case 3:
i=rnd(3)+1;
p=" While the %s slept, you smashed it %d times";
ws:
direct(x,fullhit(i),p,i); /* sleep */
return;
case 4: /* charm monster */
c[CHARMCOUNT] += c[CHARISMA]<<1;
return;
/* sonic spear */
case 5:
godirect(x,rnd(10)+15+clev," The sound damages the %s",70,'@');
return;
/* ----- LEVEL 2 SPELLS ----- */
case 6:
i=rnd(3)+2;
p=" While the %s is entangled, you hit %d times";
goto ws; /* web */
case 7:
if (c[STRCOUNT]==0) c[STREXTRA]+=3;/* strength*/
c[STRCOUNT] += 150+rnd(100);
return;
case 8:
yl = playery-5; /* enlightenment */
yh = playery+6;
xl = playerx-15;
xh = playerx+16;
vxy(&xl,&yl);
vxy(&xh,&yh); /* check bounds */
for (i=yl; i<=yh; i++) /* enlightenment */
for (j=xl; j<=xh; j++) know[j][i]=1;
draws(xl,xh+1,yl,yh+1);
return;
case 9:
raisehp(20+(clev<<1));
return; /* healing */
case 10:
c[BLINDCOUNT]=0;
return; /* cure blindness */
case 11:
createmonster(makemonst(level+1)+8);
return;
case 12:
if (rnd(11)+7 <= c[WISDOM])
direct(x,rnd(20)+20+clev," The %s believed!",0);
else
lprcat(" It didn't believe the illusions!");
return;
/* if he has the amulet of invisibility then add more time */
case 13:
for (j=i=0; i<26; i++)
if (iven[i]==OAMULET)
j+= 1+ivenarg[i];
c[INVISIBILITY] += (j<<7)+12;
return;
/* ----- LEVEL 3 SPELLS ----- */
case 14:
godirect(x,rnd(25+clev)+25+clev," The fireball hits the %s",40,'*');
return; /* fireball */
case 15:
godirect(x,rnd(25)+20+clev," Your cone of cold strikes the %s",60,'O'); /* cold */
return;
case 16:
dirpoly(x);
return; /* polymorph */
case 17:
c[CANCELLATION]+= 5+clev;
return; /* cancellation */
case 18:
c[HASTESELF]+= 7+clev;
return; /* haste self */
/* cloud kill */
case 19:
omnidirect(x,30+rnd(10)," The %s gasps for air");
return;
/* vaporize rock */
case 20:
xh = min(playerx+1,MAXX-2);
yh = min(playery+1,MAXY-2);
for (i=max(playerx-1,1); i<=xh; i++)
for (j=max(playery-1,1); j<=yh; j++) {
kn = &know[i][j];
pm = &mitem[i][j];
switch(*(p= &item[i][j])) {
case OWALL:
if (level<MAXLEVEL+MAXVLEVEL-3)
*p = *kn = 0;
break;
case OSTATUE:
if (c[HARDGAME]>3 && rnd(60)<30)
break;
*p=OBOOK;
iarg[i][j]=level;
*kn=0;
break;
case OTHRONE:
*pm=GNOMEKING;
*kn=0;
*p= OTHRONE2;
hitp[i][j]=monster[GNOMEKING].hitpoints;
break;
case OALTAR:
*pm=DEMONPRINCE;
*kn=0;
hitp[i][j]=monster[DEMONPRINCE].hitpoints;
createmonster(DEMONPRINCE);
createmonster(DEMONPRINCE);
createmonster(DEMONPRINCE);
createmonster(DEMONPRINCE);
break;
};
switch(*pm)
{ /* Xorn takes damage from vpr */
case XORN:
ifblind(i,j);
hitm(i,j,200);
break;
case TROLL:
ifblind(i,j);
hitm(i,j,200);
break;
}
}
return;
/* ----- LEVEL 4 SPELLS ----- */
case 21:/* dehydration */
direct(x,100+clev," The %s shrivels up",0);
return;
case 22: /* lightning */
godirect(x,rnd(25)+20+(clev<<1)," A lightning bolt hits the %s",1,'~');
return;
case 23:
i=min(c[HP]-1,c[HPMAX]/2); /* drain life */
direct(x,i+i,"",0);
c[HP] -= i;
return;
case 24:
if (c[GLOBE]==0) c[MOREDEFENSES] += 10;
c[GLOBE] += 200;
loseint(); /* globe of invulnerability */
return;
case 25:
omnidirect(x,32+clev," The %s struggles for air in your flood!"); /* flood */
return;
/* finger of death */
case 26:
if (rnd(151)==63) {
beep();
lprcat("\nYour heart stopped!\n");
nap(4000);
died(270);
return;
}
if (c[WISDOM]>rnd(10)+10) direct(x,2000," The %s's heart stopped",0);
else lprcat(" It didn't work");
return;
/* ----- LEVEL 5 SPELLS ----- */
/* scare monster */
case 27:
c[SCAREMONST] += rnd(10)+clev;
/* if have HANDofFEAR make last longer */
for (j=i=0; i<26; i++)
if (iven[i]==OHANDofFEAR) {
c[SCAREMONST] *= 3;
break;
}
return;
case 28:
c[HOLDMONST] += rnd(10)+clev;
return; /* hold monster */
case 29:
c[TIMESTOP] += rnd(20)+(clev<<1);
return; /* time stop */
case 30:
tdirect(x);
return; /* teleport away */
/* magic fire */
case 31:
omnidirect(x,35+rnd(10)+clev," The %s cringes from the flame");
return;
/* ----- LEVEL 6 SPELLS ----- */
case 32: /* make wall */
makewall(x);
return;
/* sphere of annihilation */
case 33:
if ((rnd(23)==5) && (wizard==0))
{
beep();
lprcat("\nYou have been enveloped by the zone of nothingness!\n");
nap(4000);
died(258);
return;
}
xl=playerx;
yl=playery;
loseint();
i=dirsub(&xl,&yl); /* get direction of sphere */
newsphere(xl,yl,i,rnd(20)+11);/*make a sphere */
return;
case 34:
genmonst();
spelknow[34]=0; /* genocide */
loseint();
return;
case 35:/* summon demon */
if (rnd(100) > 30) {
direct(x-1,150," The demon strikes at the %s",0);
return;
}
if (rnd(100) > 15) {
lprcat(" Nothing seems to have happened");
return;
}
lprcat(" The demon turned on you and vanished!");
beep();
i=rnd(40)+30;
lastnum=277;
losehp(i); /* must say killed by a demon */
return;
case 36:/* walk through walls */
c[WTW] += rnd(10)+5;
return;
case 37:/* alter reality */
{
struct isave *save;
/* pointer to item save structure */
int sc;
sc=0; /* # items saved */
save = (struct isave *)malloc(sizeof(struct isave)*MAXX*MAXY*2);
for (j=0; j<MAXY; j++)/* save all items and monsters */
for (i=0; i<MAXX; i++)
{
xl = item[i][j];
if (xl && xl!=OWALL && xl!=OANNIHILATION)
{
save[sc].type=0;
save[sc].id=item[i][j];
save[sc++].arg=iarg[i][j];
}
if (mitem[i][j])
{
save[sc].type=1;
save[sc].id=mitem[i][j];
save[sc++].arg=hitp[i][j];
}
item[i][j]=OWALL;
mitem[i][j]=0;
if (wizard) know[i][j]=1;
else know[i][j]=0;
}
eat(1,1);
if (level==1) item[33][MAXY-1]=0;
for (j=rnd(MAXY-2), i=1; i<MAXX-1; i++) item[i][j]=0;
while (sc>0) /* put objects back in level */
{
--sc;
if (save[sc].type == 0)
{
int trys;
for (trys=100, i=j=1; --trys>0 && item[i][j]; i=rnd(MAXX-1), j=rnd(MAXY-1));
if (trys) {
item[i][j]=save[sc].id;
iarg[i][j]=save[sc].arg;
}
}
else
{ /* put monsters back in */
int trys;
for (trys=100, i=j=1; --trys>0 && (item[i][j]==OWALL || mitem[i][j]); i=rnd(MAXX-1), j=rnd(MAXY-1));
if (trys) {
mitem[i][j]=save[sc].id;
hitp[i][j]=save[sc].arg;
}
}
}
loseint();
draws(0,MAXX,0,MAXY);
if (wizard==0) spelknow[37]=0;
free((char*)save);
positionplayer();
return;
}
case 38: /* permanence */
adjtime(-99999L);
spelknow[38]=0; /* forget */
loseint();
return;
default:
lprintf(" spell %d not available!",(long)x);
beep();
return;
};
}
/*
* loseint()
* Routine to subtract 1 from your int (intelligence) if > 3
*
* No arguments and no return value
*/
loseint()
{
if (--c[INTELLIGENCE]<3) c[INTELLIGENCE]=3;
}
/*
* isconfuse() Routine to check to see if player is confused
*
* This routine prints out a message saying "You can't aim your magic!"
* returns 0 if not confused, non-zero (time remaining confused)
* if confused
*/
isconfuse()
{
if (c[CONFUSE]) {
lprcat(" You can't aim your magic!");
beep();
}
return(c[CONFUSE]);
}
/* Routine to return 1 if a spell doesn't affect a monster
* nospell(x,monst)
* int x,monst;
*
* Subroutine to return 1 if the spell can't affect the monster
* otherwise returns 0
* Enter with the spell number in x, and the monster number in monst.
*/
nospell(x,monst)
int x,monst;
{
register int tmp;
/* bad spell or monst */
if (x>=SPNUM || monst>MAXMONST+8 || monst<0 || x<0) return(0);
if ((tmp=spelweird[monst-1][x])==0)
return(0);
cursors();
lprc('\n');
lprintf(spelmes[tmp],monster[monst].name);
return(1);
}
/*
* Function to return full damage against a monster (aka web)
* fullhit(xx)
* int xx;
*
* Function to return hp damage to monster due to a number of full hits
* Enter with the number of full hits being done
*/
fullhit(xx)
int xx;
{
register int i;
if (xx<0 || xx>20) return(0); /* fullhits are out of range */
if (c[LANCEDEATH]) return(10000); /* lance of death */
i = xx * ((c[WCLASS]>>1)+c[STRENGTH]+c[STREXTRA]-c[HARDGAME]-12+c[MOREDAM]);
return( (i>=1) ? i : xx );
}
/*
* Routine to direct spell damage 1 square in 1 dir
* direct(spnum,dam,str,arg)
* int spnum,dam,arg;
* char *str;
*
* Routine to ask for a direction to a spell and then hit the monster
* Enter with the spell number in spnum, the damage to be done in dam,
* lprintf format string in str, and lprintf's argument in arg.
* Returns no value.
*/
direct(spnum,dam,str,arg)
int spnum,dam,arg;
char *str;
{
int x,y;
register int m;
if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad arguments */
if (isconfuse()) return;
dirsub(&x,&y);
m = mitem[x][y];
if (item[x][y]==OMIRROR) {
if (spnum==3) /* sleep */
{
lprcat("You fall asleep! ");
beep();
fool:
arg += 2;
while (arg-- > 0) {
parse2();
nap(1000);
}
return;
}
else if (spnum==6) /* web */
{
lprcat("You get stuck in your own web! ");
beep();
goto fool;
}
else {
lastnum=278;
lprintf(str,"spell caster (thats you)",(long)arg);
beep();
losehp(dam);
return;
}
}
if (m==0) {
lprcat(" There wasn't anything there!");
return;
}
ifblind(x,y);
if (nospell(spnum,m)) {
lasthx=x;
lasthy=y;
return;
}
lprintf(str,lastmonst,(long)arg);
hitm(x,y,dam);
}
/*
* Function to perform missile attacks
* godirect(spnum,dam,str,delay,cshow)
* int spnum,dam,delay;
* char *str,cshow;
*
* Function to hit in a direction from a missile weapon and have it keep
* on going in that direction until its power is exhausted
* Enter with the spell number in spnum, the power of the weapon in hp,
* lprintf format string in str, the # of milliseconds to delay between
* locations in delay, and the character to represent the weapon in cshow.
* Returns no value.
*/
godirect(spnum,dam,str,delay,cshow)
int spnum,dam,delay;
char *str,cshow;
{
register char *p;
register int x,y,m;
int dx,dy;
if (spnum<0 || spnum>=SPNUM || str==0 || delay<0) return; /* bad args */
if (isconfuse()) return;
dirsub(&dx,&dy);
x=dx;
y=dy;
dx = x-playerx;
dy = y-playery;
x = playerx;
y = playery;
while (dam>0) {
x += dx;
y += dy;
if ((x > MAXX-1) || (y > MAXY-1) || (x < 0) || (y < 0)) {
dam=0;
break; /* out of bounds */
}
if ((x==playerx) && (y==playery)) /* if energy hits player */
{
cursors();
lprcat("\nYou are hit my your own magic!");
beep();
lastnum=278;
losehp(dam);
return;
}
if (c[BLINDCOUNT]==0) /* if not blind show effect */
{
cursor(x+1,y+1);
lprc(cshow);
nap(delay);
show1cell(x,y);
}
if ((m=mitem[x][y])) /* is there a monster there? */
{
ifblind(x,y);
if (m == LUCIFER || (m>=DEMONLORD && rnd(100)<10) ) {
dx *= -1;
dy *= -1;
cursors();
lprc('\n');
lprintf("\nthe %s returns your puny missile!", monster[m].name);
}
else {
if (nospell(spnum,m)) {
lasthx=x;
lasthy=y;
return;
}
cursors();
lprc('\n');
lprintf(str,lastmonst);
dam -= hitm(x,y,dam);
show1cell(x,y);
nap(1000);
x -= dx;
y -= dy;
}
}
else switch (*(p= &item[x][y])) {
case OWALL:
cursors();
lprc('\n');
lprintf(str,"wall");
if (dam>=50+c[HARDGAME]) /* enough damage? */
if (level<MAXLEVEL+MAXVLEVEL-3) /* not on V3 */
if ((x<MAXX-1) && (y<MAXY-1) && (x) && (y))
{
lprcat(" The wall crumbles");
god3:
*p=0;
god:
know[x][y]=0;
show1cell(x,y);
}
god2:
dam = 0;
break;
case OCLOSEDDOOR:
cursors();
lprc('\n');
lprintf(str,"door");
if (dam>=40) {
lprcat(" The door is blasted apart");
goto god3;
}
goto god2;
case OSTATUE:
cursors();
lprc('\n');
lprintf(str,"statue");
if (dam>44) {
if (c[HARDGAME] > 3 && rnd(60)<30)
goto god2;
lprcat(" The statue crumbles");
*p=OBOOK;
iarg[x][y]=level;
goto god;
}
goto god2;
case OTHRONE:
cursors();
lprc('\n');
lprintf(str,"throne");
if (dam>33) {
mitem[x][y]=GNOMEKING;
hitp[x][y]=monster[GNOMEKING].hitpoints;
*p = OTHRONE2;
goto god;
}
goto god2;
case OMIRROR:
dx *= -1;
dy *= -1;
break;
};
dam -= 3 + (c[HARDGAME]>>1);
}
}
/*
* Routine to put "monster" or the monster name into lastmosnt
* ifblind(x,y)
* int x,y;
*
* Subroutine to copy the word "monster" into lastmonst if the player is
* blind. Enter with the coordinates (x,y) of the monster
* Returns no value.
*/
ifblind(x,y)
int x,y;
{
char *p;
vxy(&x,&y); /* verify correct x,y coordinates */
if (c[BLINDCOUNT]) {
lastnum=279;
p="monster";
}
else {
lastnum=mitem[x][y];
p=monster[lastnum].name;
}
strcpy(lastmonst,p);
}
/*
* tdirect(spnum) Routine to teleport away a monster
* int spnum;
*
* Routine to ask for a direction to a spell and then teleport away monster
* Enter with the spell number that wants to teleport away
* Returns no value.
*/
tdirect(spnum)
int spnum;
{
int x,y;
register int m;
if (spnum<0 || spnum>=SPNUM) return; /* bad args */
if (isconfuse()) return;
dirsub(&x,&y);
if ((m=mitem[x][y])==0)
{
lprcat(" There wasn't anything there!");
return;
}
ifblind(x,y);
if (nospell(spnum,m)) {
lasthx=x;
lasthy=y;
return;
}
fillmonst(m);
mitem[x][y]=know[x][y]=0;
}
makewall(spnum)
int spnum;
{
int x,y;
if (spnum<0 || spnum>=SPNUM) return; /* bad args */
if (isconfuse()) return;
dirsub(&x,&y);
if ((y>=0) && (y<=MAXY-1) && (x>=0) && (x<=MAXX-1)) /* within bounds? */
if (item[x][y]!=OWALL) { /* can't make anything on walls */
if (item[x][y]==0){ /* is it free of items? */
if (mitem[x][y]==0){ /*is it free of monsters? */
if ((level!=1) || (x!=33) || (y!=MAXY-1)) {
item[x][y]=OWALL;
know[x][y]=1;
show1cell(x,y);
}
else lprcat("\nyou can't make a wall there!");
}
else lprcat("\nthere's a monster there!");
}
else lprcat("\nthere's something there already!");
}
else lprcat("\nthere's a wall there already!");
}
/*
* omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player
* int sp,dam;
* char *str;
*
* Routine to cast a spell and then hit the monster in all directions
* Enter with the spell number in sp, the damage done to wach square in dam,
* and the lprintf string to identify the spell in str.
* Returns no value.
*/
omnidirect(spnum,dam,str)
int spnum,dam;
char *str;
{
register int x,y,m;
if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad args */
for (x=playerx-1; x<playerx+2; x++)
for (y=playery-1; y<playery+2; y++)
{
if (m=mitem[x][y])
if (nospell(spnum,m) == 0)
{
ifblind(x,y);
cursors();
lprc('\n');
lprintf(str,lastmonst);
hitm(x,y,dam);
nap(800);
}
else {
lasthx=x;
lasthy=y;
}
}
}
/*
* Routine to ask for direction, then modify x,y for it
* static dirsub(x,y)
* int *x,*y;
*
* Function to ask for a direction and modify an x,y for that direction
* Enter with the origination coordinates in (x,y).
* Returns index into diroffx[] (0-8).
*/
dirsub(x,y)
int *x,*y;
{
register int i;
lprcat("\nIn What Direction? ");
for (i=0; ; )
switch(getcharacter())
{
case 'b':
i++;
case 'n':
i++;
case 'y':
i++;
case 'u':
i++;
case 'h':
i++;
case 'k':
i++;
case 'l':
i++;
case 'j':
i++;
goto out;
};
out:
*x = playerx+diroffx[i];
*y = playery+diroffy[i];
vxy(x,y);
return(i);
}
/*
* vxy(x,y) Routine to verify/fix coordinates for being within bounds
* int *x,*y;
*
* Function to verify x & y are within the bounds for a level
* If *x or *y is not within the absolute bounds for a level, fix them so that
* they are on the level.
* Returns TRUE if it was out of bounds, and the *x & *y in the calling
* routine are affected.
*/
vxy(x,y)
int *x,*y;
{
int flag=0;
if (*x<0) {
*x=0;
flag++;
}
if (*y<0) {
*y=0;
flag++;
}
if (*x>=MAXX) {
*x=MAXX-1;
flag++;
}
if (*y>=MAXY) {
*y=MAXY-1;
flag++;
}
return(flag);
}
/*
* dirpoly(spnum) Routine to ask for a direction and polymorph a monst
* int spnum;
*
* Subroutine to polymorph a monster and ask for the direction its in
* Enter with the spell number in spmun.
* Returns no value.
*/
dirpoly(spnum)
int spnum;
{
int x,y,m;
if (spnum<0 || spnum>=SPNUM) return; /* bad args */
if (isconfuse()) return; /* if he is confused, he can't aim his magic */
dirsub(&x,&y);
if (mitem[x][y]==0)
{
lprcat(" There wasn't anything there!");
return;
}
ifblind(x,y);
if (nospell(spnum,mitem[x][y])) {
lasthx=x;
lasthy=y;
return;
}
while ( monster[m = mitem[x][y] = rnd(MAXMONST+7)].genocided );
hitp[x][y] = monster[m].hitpoints;
show1cell(x,y); /* show the new monster */
}
/*
* Function to hit a monster at the designated coordinates
* hitmonster(x,y)
* int x,y;
*
* This routine is used for a bash & slash type attack on a monster
* Enter with the coordinates of the monster in (x,y).
* Returns no value.
*/
hitmonster(x,y)
int x,y;
{
register int tmp,monst,damag,flag;
if (c[TIMESTOP]) return; /* not if time stopped */
vxy(&x,&y); /* verify coordinates are within range */
if ((monst = mitem[x][y]) == 0) return;
hit3flag=1;
ifblind(x,y);
tmp = monster[monst].armorclass + c[LEVEL] + c[DEXTERITY] + c[WCLASS/4] -12
- c[HARDGAME];
cursors();
/* need at least random chance to hit */
if ((rnd(20) < tmp) || (rnd(71) < 5)) {
lprcat("\nYou hit");
flag=1;
damag = fullhit(1);
if (damag<9999) damag=rnd(damag)+1;
}
else {
lprcat("\nYou missed");
flag=0;
}
lprcat(" the ");
lprcat(lastmonst);
/* lprintf(" (tmp = %d)", tmp); */
if (flag) /* if the monster was hit */
if (iven[c[WIELD]] != OSWORDofSLASHING)
if ((monst==RUSTMONSTER) || (monst==DISENCHANTRESS) || (monst==CUBE))
if (c[WIELD]>0)
if (ivenarg[c[WIELD]] > -10) {
lprintf("\nYour weapon is dulled by the %s",lastmonst);
beep();
--ivenarg[c[WIELD]];
}
if (flag) {
hitm(x,y,damag);
if ((monst >= DEMONLORD) &&
(c[LANCEDEATH]) &&
(hitp[x][y]) )
lprintf("\nYour lance of death tickles the %s!",lastmonst);
}
/*
if (monst == VAMPIRE)
if (hitp[x][y]<25)
{ mitem[x][y]=LEMMING;
know[x][y]=0;
}
*/
if (monst == METAMORPH)
if (hitp[x][y]<25 && hitp[x][y] > 0)
mitem[x][y]=BRONZEDRAGON+rund(9);
if (mitem[x][y]==LEMMING)
if (rnd(100)<=40) createmonster(LEMMING);
}
/*
* Function to just hit a monster at a given coordinates
* hitm(x,y,amt)
* int x,y,amt;
*
* Returns the number of hitpoints the monster absorbed
*This routine is used to specifically damage a monster at a location (x,y)
* Called by hitmonster(x,y)
*/
hitm(x,y,amt)
int x,y;
register amt;
{
register int monst;
int hpoints,amt2;
vxy(&x,&y); /* verify coordinates are within range */
amt2 = amt; /* save initial damage so we can return it */
monst = mitem[x][y];
/* if half damage curse adjust damage points */
if (c[HALFDAM]) amt >>= 1;
if (amt<=0) amt2 = amt = 1;
lasthx=x;
lasthy=y;
/* make sure hitting monst breaks stealth condition */
stealth[x][y]=1;
c[HOLDMONST]=0; /* hit a monster breaks hold monster spell */
switch(monst) /* if a dragon and orb(s) of dragon slaying */
{
case WHITEDRAGON:
case REDDRAGON:
case GREENDRAGON:
case BRONZEDRAGON:
case PLATINUMDRAGON:
case SILVERDRAGON:
if (c[SLAYING])
amt *= 3;
break;
}
/* invincible monster fix is here */
if (hitp[x][y] > monster[monst].hitpoints)
hitp[x][y] = monster[monst].hitpoints;
if (monst >= DEMONLORD) {
if (c[LANCEDEATH])
amt=300;
if (iven[c[WIELD]] == OSLAYER)
amt=10000;
}
if ((hpoints = hitp[x][y]) <= amt) {
lprintf("\nThe %s died!",lastmonst);
raiseexperience((long)monster[monst].experience);
amt = monster[monst].gold;
if (amt>0) dropgold(rnd(amt)+amt);
dropsomething(monst);
disappear(x,y);
bottomline();
hitp[x][y] = 0;
return(hpoints);
}
hitp[x][y] = hpoints-amt;
return(amt2);
}
/*
* Function for the monster to hit the player from (x,y)
* hitplayer(x,y)
* int x,y;
*
* Function for the monster to hit the player with monster at location x,y
* Returns nothing of value.
*/
hitplayer(x,y)
int x,y;
{
register int dam,tmp,mster,bias;
vxy(&x,&y); /* verify coordinates are within range */
lastnum = mster = mitem[x][y];
if ((know[x][y]&1) == 0) {
know[x][y]=1;
show1cell(x,y);
}
bias = (c[HARDGAME]) + 1;
hitflag = hit2flag = hit3flag = 1;
yrepcount=0;
cursors();
ifblind(x,y);
if (mster < DEMONLORD)
if (c[INVISIBILITY]) if (rnd(33)<20) {
lprintf("\nThe %s misses wildly",lastmonst);
return;
}
if ( (mster < DEMONLORD) && (mster != PLATINUMDRAGON) )
if (c[CHARMCOUNT])
if (rnd(30)+5*monster[mster].level-c[CHARISMA]<30) {
lprintf("\nThe %s is awestruck at your magnificence!",lastmonst);
return;
}
if (mster==LEMMING) return;
else {
dam = monster[mster].damage;
dam += rnd( (int) ((dam<1)?1:dam) ) + monster[mster].level;
}
/* demon lords/prince/god of hellfire damage is reduced if wielding
Slayer */
if (mster >= DEMONLORD)
if (iven[c[WIELD]]==OSLAYER)
dam=(int) (1 - (0.1 * rnd(5)) * dam);
/* spirit naga's and poltergeist's damage is halved if scarab of
negate spirit */
if (c[NEGATESPIRIT] || c[SPIRITPRO])
if ((mster ==POLTERGEIST) || (mster ==SPIRITNAGA))
dam = (int) dam/2;
/* halved if undead and cube of undead control */
if (c[CUBEofUNDEAD] || c[UNDEADPRO])
if ((mster ==VAMPIRE) || (mster ==WRAITH) || (mster ==ZOMBIE))
dam = (int) dam/2;
tmp = 0;
if (monster[mster].attack>0)
if (((dam + bias + 8) > c[AC])
|| (rnd((int)((c[AC]>0)?c[AC]:1))==1)) {
if (spattack(monster[mster].attack,x,y)) {
flushall();
return;
}
tmp = 1;
bias -= 2;
cursors();
}
if (((dam + bias) > c[AC]) || (rnd((int)((c[AC]>0)?c[AC]:1))==1)) {
lprintf("\n The %s hit you ",lastmonst);
tmp = 1;
if ((dam -= c[AC]) < 0)
dam=0;
if (dam > 0) {
losehp(dam);
bottomhp();
flushall();
}
}
if (tmp == 0)
lprintf("\n The %s missed ",lastmonst);
}
/*
* dropsomething(monst) Function to create an object when a monster dies
* int monst;
*
* Function to create an object near the player when
* certain monsters are killed
* Enter with the monster number
* Returns nothing of value.
*/
dropsomething(monst)
int monst;
{
switch(monst) {
case ORC:
case NYMPH:
case ELF:
case TROGLODYTE:
case TROLL:
case ROTHE:
case VIOLETFUNGI:
case PLATINUMDRAGON:
case GNOMEKING:
case REDDRAGON:
something(level);
return;
case LEPRECHAUN:
if (rnd(101)>=75) creategem();
if (rnd(5)==1) dropsomething(LEPRECHAUN);
return;
case LEMMING: /* createitem(OGOLDPILE,1); */
return;
}
}
/*
* dropgold(amount) Function to drop some gold around player
* int amount;
*
* Enter with the number of gold pieces to drop
* Returns nothing of value.
*/
dropgold(amount)
register int amount;
{
if (amount > 250) createitem(OMAXGOLD, amount);
else createitem(OGOLDPILE,amount);
}
/*
* something(level) Function to create a random item around player
* int level;
*
* Function to create an item from a designed probability around player
* Enter with the cave level on which something is to be dropped
* Returns nothing of value.
*/
something(lev)
int lev;
{
register int j;
int i;
if (lev<0 || lev>MAXLEVEL+MAXVLEVEL)
return; /* correct level? */
if (rnd(101)<8)
something(lev); /* possibly more than one item */
j = newobject(lev,&i);
createitem(j,i);
}
/*
* newobject(lev,i) Routine to return a randomly selected new object
* int lev,*i;
*
* Routine to return a randomly selected object to be created
* Returns the object number created, and sets *i for its argument
* Enter with the cave level and a pointer to the items arg
*/
static char nobjtab[] =
{
0, OSCROLL, OSCROLL, OSCROLL, OSCROLL, OPOTION,
OPOTION, OPOTION, OPOTION, OGOLDPILE, OGOLDPILE, OGOLDPILE, OGOLDPILE,
OBOOK, OBOOK, OBOOK, OBOOK, ODAGGER, ODAGGER, ODAGGER, OLEATHER, OLEATHER,
OLEATHER, OREGENRING, OPROTRING, OENERGYRING, ODEXRING, OSTRRING, OSPEAR,
OBELT, ORING, OSTUDLEATHER, OSHIELD, OFLAIL, OCHAIN, O2SWORD, OPLATE,
OLONGSWORD };
newobject(lev,i)
register int lev,*i;
{
register int tmp=32,j;
if (level<0 || level>MAXLEVEL+MAXVLEVEL)
return(0); /* correct level? */
if (lev>6) tmp=37;
else if (lev>4) tmp=35;
j = nobjtab[tmp=rnd(tmp)]; /* the object type */
switch(tmp) {
case 1:
case 2:
case 3:
case 4:
*i=newscroll();
break;
case 5:
case 6:
case 7:
case 8:
*i=newpotion();
break;
case 9:
case 10:
case 11:
case 12:
*i=rnd((lev+1)*10)+lev*10+10;
break;
case 13:
case 14:
case 15:
case 16:
*i=lev;
break;
case 17:
case 18:
case 19:
if (!(*i=newdagger())) return(0);
break;
case 20:
case 21:
case 22:
if (!(*i=newleather())) return(0);
break;
case 23:
case 32:
case 35:
*i=rund(lev/3+1);
break;
case 24:
case 26:
*i=rnd(lev/4+1);
break;
case 25:
*i=rund(lev/4+1);
break;
case 27:
*i=rnd(lev/2+1);
break;
case 28:
*i=rund(lev/3+1);
if (*i==0) return(0);
break;
case 29:
case 31:
*i=rund(lev/2+1);
if (*i==0) return(0);
break;
case 30:
case 33:
*i=rund(lev/2+1);
break;
case 34:
*i=newchain();
break;
case 36:
*i=newplate();
break;
case 37:
*i=newsword();
break;
}
return(j);
}
/*
* Function to process special attacks from monsters
* spattack(atckno,xx,yy)
* int atckno,xx,yy;
*
* Enter with the special attack number, and the coordinates (xx,yy)
* of the monster that is special attacking
* Returns 1 if must do a show1cell(xx,yy) upon return, 0 otherwise
*
* atckno monster effect
* ---------------------------------------------------
* 0 none
* 1 rust monster eat armor
* 2 hell hound breathe light fire
* 3 dragon breathe fire
* 4 giant centipede weakening sing
* 5 white dragon cold breath
* 6 wraith drain level
* 7 waterlord water gusher
* 8 leprechaun steal gold
* 9 disenchantress disenchant weapon or armor
* 10 ice lizard hits with barbed tail
* 11 umber hulk confusion
* 12 spirit naga cast spells taken from special attacks
* 13 platinum dragon psionics
* 14 nymph steal objects
* 15 bugbear bite
* 16 osequip bite
*
* char rustarm[ARMORTYPES][2];
* special array for maximum rust damage to armor from rustmonster
* format is: { armor type , minimum attribute
*/
#define ARMORTYPES 6
static char rustarm[ARMORTYPES][2] =
{
OSTUDLEATHER,-2,ORING,-4, OCHAIN,-5, OSPLINT,-6,OPLATE,-8,OPLATEARMOR,-9 };
static char spsel[] = {
1, 2, 3, 5, 6, 8, 9, 11, 13, 14 };
spattack(x,xx,yy)
int x,xx,yy;
{
register int i,j=0,k,m;
register char *p=0;
vxy(&xx,&yy); /* verify x & y coordinates */
/* cancel only works 5% of time for demon prince
and god */
if (c[CANCELLATION])
if (mitem[xx][yy] >= DEMONPRINCE) {
if (rnd(100) >= 95) return(0);
}
else return(0);
/* staff of power cancels demonlords/wraiths/vampires 75% of time */
if (mitem[xx][yy] != LUCIFER) {
if ( (mitem[xx][yy] >= DEMONLORD) ||
(mitem[xx][yy] == WRAITH) ||
(mitem[xx][yy] == VAMPIRE) )
for (i=0;i<26;i++)
if (iven[i]==OPSTAFF)
if (rnd(100)<75)
return(0);
}
/* if have cube of undead control, wraiths and vampires do nothing */
if ( (mitem[xx][yy]==WRAITH) || (mitem[xx][yy]==VAMPIRE) )
if ( (c[CUBEofUNDEAD]) || (c[UNDEADPRO]) )
return(0);
switch(x) {
case 1: /* rust your armor, j=1 when rusting has occurred */
m = k = c[WEAR];
if ((i=c[SHIELD]) != -1)
if (--ivenarg[i] < -1)
ivenarg[i]= -1;
else j=1;
if ((j==0) && (k != -1)) {
m = iven[k];
for (i=0; i<ARMORTYPES; i++)
if (m == rustarm[i][0])
/* find his armor in table */
{
if (--ivenarg[k]< rustarm[i][1])
ivenarg[k]= rustarm[i][1];
else j=1;
break;
}
}
if (j==0) /* if rusting did not occur */
switch(m) {
case OLEATHER:
p = "\nThe %s hit you -- You are lucky you have leather on";
break;
case OSSPLATE:
p = "\nThe %s hit you -- You are fortunate to have stainless steel armor!";
break;
case OELVENCHAIN:
p = "\nThe %s hit you -- You are very lucky to have such strong elven chain!";
break;
}
else {
beep();
p = "\nThe %s hit you -- your armor feels weaker";
}
break;
case 2:
i = rnd(15)+8-c[AC];
spout:
p="\nThe %s breathes fire at you!";
if (c[FIRERESISTANCE])
p="\nThe %s's flame doesn't phase you!";
else
spout2:
if (p) {
lprintf(p,lastmonst);
beep();
}
checkloss(i);
return(0);
case 3:
i = rnd(20)+25-c[AC];
goto spout;
case 4:
if (c[STRENGTH]>3) {
p="\nThe %s stung you! You feel weaker";
beep();
if (--c[STRENGTH] < 3)
c[STRENGTH] = 3;
}
else p="\nThe %s stung you!";
break;
case 5:
p="\nThe %s blasts you with his cold breath";
i = rnd(15)+18-c[AC];
goto spout2;
case 6:
lprintf("\nThe %s drains you of your life energy!",lastmonst);
loselevel();
if (mitem[xx][yy]==DEMONPRINCE) losemspells(1);
if (mitem[xx][yy]==LUCIFER) {
loselevel();
losemspells(2);
for (i=0;i<=5;i++)
if (c[i]-- < 3) c[i]=3;
}
beep();
return(0);
case 7:
p="\nThe %s got you with a gusher!";
i = rnd(15)+25-c[AC];
goto spout2;
case 8:
if (c[NOTHEFT]) return(0);
/* he has a device of no theft */
if (c[GOLD]) {
p="\nThe %s hit you -- Your purse feels lighter";
if (c[GOLD]>32767) c[GOLD]>>=1;
else c[GOLD] -= rnd((int)(1+(c[GOLD]>>1)));
if (c[GOLD] < 0) c[GOLD]=0;
}
else p="\nThe %s couldn't find any gold to steal";
lprintf(p,lastmonst);
disappear(xx,yy);
beep();
bottomgold();
return(1);
case 9:
for(j=50; ; ) /* disenchant */
{
i=rund(26);
m=iven[i]; /* randomly select item */
if (m>0 && ivenarg[i]>0 && m!=OSCROLL && m!=OPOTION)
{
if ((ivenarg[i] -= 3)<0) ivenarg[i]=0;
lprintf("\nThe %s hits you with a spell of disenchantment! ",lastmonst);
srcount=0;
beep();
show3(i);
bottomline();
return(0);
}
if (--j<=0) {
p="\nThe %s nearly misses";
break;
}
break;
}
break;
case 10:
p="\nThe %s hit you with his barbed tail";
i = rnd(25)-c[AC];
goto spout2;
case 11:
p="\nThe %s has confused you";
beep();
c[CONFUSE]+= 10+rnd(10);
break;
case 12:/*performs any number of other special attacks */
return(spattack(spsel[rund(10)],xx,yy));
case 13:
p="\nThe %s flattens you with his psionics!";
i = rnd(15)+30-c[AC];
goto spout2;
case 14:
if (c[NOTHEFT]) return(0);
/* he has device of no theft */
if (emptyhanded()==1) {
p="\nThe %s couldn't find anything to steal";
break;
}
lprintf("\nThe %s picks your pocket and takes:",lastmonst);
beep();
if (stealsomething()==0) lprcat(" nothing");
disappear(xx,yy);
bottomline();
return(1);
case 15:
i= rnd(10)+ 5-c[AC];
spout3:
p="\nThe %s bit you!";
goto spout2;
case 16:
i= rnd(15)+10-c[AC];
goto spout3;
};
if (p) {
lprintf(p,lastmonst);
bottomline();
}
return(0);
}
/*
* Routine to subtract hp from user and flag bottomline display
* checkloss(x)
* int x;
*
* Enter with the number of hit points to lose
* Note: if x > c[HP] this routine could kill the player!
*/
checkloss(x)
int x;
{
if (x>0) {
losehp(x);
bottomhp();
}
}
/*
* Routine to annihilate all monsters around player (playerx,playery)
* annihilate()
*
* Gives player experience, but no dropped objects
* Returns the experience gained from all monsters killed
*/
annihilate()
{
int i,j;
register long k;
register char *p;
for (k=0, i=playerx-1; i<=playerx+1; i++)
for (j=playery-1; j<=playery+1; j++)
if (!vxy(&i,&j)) /* if not out of bounds */
if (*(p= &mitem[i][j])) /* if a monster there */
if (*p<DEMONLORD) {
k += monster[*p].experience;
*p=know[i][j]=0;
}
else {
lprintf("\nThe %s barely escapes being annihilated!",monster[*p].name);
hitp[i][j] = (hitp[i][j]>>1) + 1;
/* lose half hit points*/
}
if (k>0) {
lprcat("\nYou hear loud screams of agony!");
raiseexperience((long)k);
}
return(k);
}
/*
* Function to create a new sphere of annihilation
* newsphere(x,y,dir,lifetime)
* int x,y,dir,lifetime;
*
* Enter with the coordinates of the sphere in x,y
* the direction (0-8 diroffx format) in dir, and the lifespan of the
* sphere in lifetime (in turns)
* Returns the number of spheres currently in existence
*/
newsphere(x,y,dir,life)
int x,y,dir,life;
{
int m,i;
struct sphere *sp;
if (((sp=(struct sphere *)malloc(sizeof(struct sphere)))) == 0)
return(c[SPHCAST]); /* can't malloc, therefore failure */
if (dir>=9) dir=0; /* no movement if direction not found */
if (level==0) vxy(&x,&y); /* don't go out of bounds */
else {
if (x<1) x=1;
if (x>=MAXX-1) x=MAXX-2;
if (y<1) y=1;
if (y>=MAXY-1) y=MAXY-2;
}
for (i=0;i<26;i++)
if (iven[i]==OSPHTALISMAN) goto out;
/* demons dispel spheres */
if ((m=mitem[x][y]) >= DEMONLORD) {
i = hitp[x][y];
know[x][y]=1;
show1cell(x,y); /* show the demon (ha ha) */
cursors();
lprintf("\nThe %s dispels the sphere!",monster[m].name);
beep();
rmsphere(x,y); /* remove any spheres that are here */
mitem[x][y] = m;
hitp[x][y] = i;
know[x][y]=0;
return(c[SPHCAST]);
}
/* disenchantress cancels spheres */
if (m==DISENCHANTRESS) {
cursors();
lprintf("\nThe %s causes cancellation of the sphere!",monster[m].name);
beep();
boom:
sphboom(x,y); /* blow up stuff around sphere */
rmsphere(x,y); /* remove any spheres that are here */
return(c[SPHCAST]);
}
/* cancellation cancels spheres */
if (c[CANCELLATION]) {
cursors();
lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!");
beep();
goto boom;
}
/* collision of sphere and player! */
if (playerx==x && playery==y) {
cursors();
lprcat("\nYou have been enveloped by the zone of nothingness!\n");
beep();
rmsphere(x,y); /* remove any spheres that are here */
nap(4000);
died(258);
}
out:
/* collision of spheres detonates spheres */
if (item[x][y]==OANNIHILATION) {
cursors();
lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!");
beep();
rmsphere(x,y);
goto boom;
}
item[x][y]=OANNIHILATION;
mitem[x][y]=0;
know[x][y]=1;
show1cell(x,y); /* show the new sphere */
sp->x=x;
sp->y=y;
sp->lev=level;
sp->dir=dir;
sp->lifetime=life;
sp->p=0;
if (spheres==0) spheres=sp; /* if first node in the sphere list */
else /* add sphere to beginning of linked list */
{
sp->p = spheres;
spheres = sp;
}
return(++c[SPHCAST]); /* one more sphere in the world */
}
/*
* rmsphere(x,y) Function to delete a sphere of annihilation from list
* int x,y;
*
* Enter with the coordinates of the sphere (on current level)
* Returns the number of spheres currently in existence
*/
rmsphere(x,y)
int x,y;
{
register struct sphere *sp,*sp2=0;
for (sp=spheres; sp; sp2=sp,sp=sp->p)
if (level==sp->lev) /* is sphere on this level? */
if ((x==sp->x) && (y==sp->y))
/* locate sphere at this location */
{
item[x][y]= mitem[x][y]= 0;
know[x][y]=1;
show1cell(x,y); /* show the now missing sphere */
--c[SPHCAST];
if (sp==spheres) {
sp2=sp;
spheres=sp->p;
free((char*)sp2);
}
else
{
sp2->p = sp->p;
free((char*)sp);
}
break;
}
return(c[SPHCAST]); /* return number of spheres in the world */
}
/*
* sphboom(x,y) Function to perform the effects of a sphere detonation
* int x,y;
*
* Enter with the coordinates of the blast, Returns no value
*/
sphboom(x,y)
int x,y;
{
register int i,j,k;
if (c[HOLDMONST]) c[HOLDMONST]=1;
if (c[CANCELLATION]) c[CANCELLATION]=1;
for (j=max(1,x-2); j<min(x+3,MAXX-1); j++)
for (i=max(1,y-2); i<min(y+3,MAXY-1); i++)
{
item[j][i]=mitem[j][i]=0;
show1cell(j,i);
for (k=0;k<26;k++) if (iven[k]==OSPHTALISMAN) return;
if (playerx==j && playery==i)
{
cursors();
beep();
lprcat("\nYou were too close to the sphere!");
nap(3000);
died(283); /* player killed in explosion */
}
}
}
/*
* Function to ask for monster and genocide from game
* genmonst()
*
* This is done by setting a flag in the monster[] structure
*/
genmonst()
{
register int i,j;
cursors();
lprcat("\nGenocide what monster? ");
for (i=0; (!isalpha(i)) && (i!=' '); i=getcharacter());
lprc(i);
for (j=0; j<MAXMONST; j++) /* search for the monster type */
if (monstnamelist[j]==i) /* have we found it? */
if (monster[j].genocided==0) {
monster[j].genocided=1; /* genocided from game */
lprintf(" There will be no more %s's",monster[j].name);
/* now wipe out monsters on this level */
newcavelevel(level);
draws(0,MAXX,0,MAXY);
bot_linex();
return;
}
lprcat(" You sense failure!");
}